package com.cltech.frame.base;

import com.cltech.frame.transformer.BeanTransformerAdapter;
import org.hibernate.SQLQuery;
import org.hibernate.transform.Transformers;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.io.Serializable;
import java.math.BigInteger;
import java.util.List;
import java.util.Map;

/**
 * 数据库操作基类.
 *
 * @author guanbo
 * @version 1.0.0.0
 * @param <T> 实体
 * @param <ID> 实体
 */
public class BaseRepositoryImpl  <T, ID extends Serializable> extends SimpleJpaRepository<T, ID>
        implements BaseRepository<T, ID>{
    /**
     * entityManager.
     */
    private final EntityManager entityManager;
    /**
     * jpaEntityInformation.
     */
    private JpaEntityInformation<T, ID> jpaEntityInformation;

    /**
     * 构造函数.
     * @param jpaEntityInformation  jpaEntityInformation
     * @param entityManager entityManager
     */
    public BaseRepositoryImpl(final JpaEntityInformation<T, ID> jpaEntityInformation, final EntityManager entityManager) {
        super(jpaEntityInformation, entityManager);
        this.entityManager = entityManager;
        this.jpaEntityInformation = jpaEntityInformation;
    }
    @Override
    public <D> List<D> listBySQL(final Class<D> clazz, final String sql, final List<Object> values) {
        final Query nativeQuery = entityManager.createNativeQuery(sql);
        if(null!=values){
            for (int i = 0; i < values.size(); i++) {
                nativeQuery.setParameter(i + 1, values.get(i));
            }
        }

        nativeQuery.unwrap(SQLQuery.class).setResultTransformer(new BeanTransformerAdapter(clazz));
        return nativeQuery.getResultList();
    }

    @Override
    public List<Map<String, Object>> listBySQL(final String sql, final List<Object> values) {
        final Query nativeQuery = entityManager.createNativeQuery(sql);
        if(null!=values){
            for (int i = 0; i < values.size(); i++) {
                nativeQuery.setParameter(i + 1, values.get(i));
            }
        }
        nativeQuery.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        return nativeQuery.getResultList();
    }

    @Override
    public Long countBySQL(final String sql, final List<Object> values) {
        final Query nativeQuery = entityManager.createNativeQuery(sql);
        if(null!=values){
            for (int i = 0; i < values.size(); i++) {
                nativeQuery.setParameter(i + 1, values.get(i));
            }
        }
        return ((BigInteger) nativeQuery.getSingleResult()).longValue();
    }

    @Override
    public void detach(T entity) {
        entityManager.detach(entity);
    }

    @Override
    public void clear() {
        entityManager.clear();
    }
}
